using System;
using Scenario.WorkflowEngine.DataModel;

namespace Scenario.WorkflowEngine.DataModel.WorkflowProcesses
{
	//*********************************************************************
	//
	// Workflow Class
	//
	// The XmlWorkflow class represents the template of a process
	//
	//*********************************************************************
	public class XMLWorkflow : bOS.XML.Data.XMLObject 
	{
		public const string MAIN_NODE	= "WorkflowProcess";

		private const string NAME_ATTRIBUTE		= "Name";
		private const string DESCRIPTION_NODE	= "Description";
		private const string PARENTPROCESS_NODE	= "ParentProcess";
		private const string STATUS_NODE		= "Status";
		private const string PROCESSID_NODE		= "ProcessId";

		public const string CREATED_STATUS		= "CREATED";
		public const string QUEUED_STATUS		= "QUEUED";
		public const string RUNNING_STATUS		= "RUNNING";
		public const string COMPLETED_STATUS	= "COMPLETED";
		public const string ERROR_STATUS		= "ERROR";

		private string sName;
		private string sDescription;
		private string parentProcess;
		private string sStatus;
		private string processId;

		private XMLTransitions vTransitions;
        private XMLMessages vMessages;
		private XMLActivities vActivities;
		private WorkflowRelevantData.XMLAttributes vVariables;

		public XMLWorkflow()
		{
			this.Init();
		}

		public XMLWorkflow(System.Xml.XmlNode workflow)
		{
			this.Parse(workflow);
		}

		public XMLTransitions XMLTransitions 
		{
			get { return vTransitions; }
			set { vTransitions = value; }
		}

        public XMLMessages XMLMessages
        {
            get { return vMessages; }
            set { vMessages = value; }
        }

		public XMLActivities XMLActivities 
		{
			get { return vActivities; }
			set { vActivities = value; }
		}

		public WorkflowRelevantData.XMLAttributes XMLAttributes 
		{
			get { return vVariables; }
			set { vVariables = value; }
		}

		public string ProcessId
		{
			get { return processId;}
			set { processId = value;}
		}

		public string Name 
		{
			get { return sName; }
			set { sName = value; }
		}

		public string Description 
		{
			get { return sDescription; }
			set { sDescription = value; }
		}

		public string ParentProcess
		{
			get {return parentProcess;}
			set {parentProcess = value;}
		}

		public string Status
		{
			get { return sStatus;}
			set { sStatus = value;}
		}

		override public void Init()
		{
			processId = "";
			sName= string.Empty;
			sDescription= string.Empty;
			sStatus = string.Empty;

			vActivities = new XMLActivities();
			vTransitions = new XMLTransitions();
            vMessages = new XMLMessages();
			vVariables = new WorkflowRelevantData.XMLAttributes();
		}
		
		override public void Parse(System.Xml.XmlNode node2Parse)
		{
			this.Init();

			System.Xml.XmlNode node;

			/** find the attributes situated on the root tag **/
			for ( int i=0; i<node2Parse.Attributes.Count;i++)
			{
				node = node2Parse.Attributes.Item(i);

				switch ( node.Name )
				{
					case XMLWorkflow.NAME_ATTRIBUTE:
						sName = node.InnerText;
						break;
				}
			}	

			/** find the sub tags witch contains values **/
			for ( int i=0; i<node2Parse.ChildNodes.Count; i++)
			{
				node = node2Parse.ChildNodes[i];

				switch ( node.Name )
				{
					case XMLWorkflow.PROCESSID_NODE:
						processId = node.InnerText;
						break;

					case XMLWorkflow.DESCRIPTION_NODE:
						sDescription=node.InnerText;
						break;
					
					case XMLWorkflow.PARENTPROCESS_NODE:
						parentProcess = node.InnerText;
						break;

					//ActivitySet subcollection
					case XMLActivities.MAIN_NODE:
						vActivities.Parse(node);
						break;

					//Transitions subcollection
					case XMLTransitions.MAIN_NODE:
						vTransitions.Parse(node);
						break;

                    case XMLMessages.MAIN_NODE:
                        vMessages.Parse(node);
                        break;


					//Attributes subcollection
					case WorkflowRelevantData.XMLAttributes.MAIN_NODE:
						vVariables.Parse(node);
						break;

					case XMLWorkflow.STATUS_NODE:
						sStatus = node.InnerText;
						break;
				}
			}
		}

		override public bOS.XML.XMLNode GetXMLNode()
		{
			bOS.XML.XMLNode xmlNode = new bOS.XML.XMLNode(XMLWorkflow.MAIN_NODE);
			xmlNode.AddAttribute ( new bOS.XML.XMLAttribute (XMLWorkflow.NAME_ATTRIBUTE, sName) );
			xmlNode.AddNode ( new bOS.XML.XMLNode (XMLWorkflow.DESCRIPTION_NODE, sDescription) );
			xmlNode.AddNode ( new bOS.XML.XMLNode (XMLWorkflow.PARENTPROCESS_NODE, parentProcess) );
			xmlNode.AddNode ( new bOS.XML.XMLNode (XMLWorkflow.STATUS_NODE, sStatus) );
			xmlNode.AddNode ( new bOS.XML.XMLNode (XMLWorkflow.PROCESSID_NODE, processId) );
			xmlNode.AddNode ( vActivities.GetXMLNode() );
			xmlNode.AddNode ( vTransitions.GetXMLNode() );
            xmlNode.AddNode(vMessages.GetXMLNode());
			xmlNode.AddNode ( vVariables.GetXMLNode() );
			
			return xmlNode;
		}

		override public string GetXML()
		{
			return this.GetXMLNode().GetXML(true, 0);
		}

		public void AddTransitions(XMLTransitions _Transitions)
		{
			for ( int i=0; i<_Transitions.Count; i++)
			{
				vTransitions.Add ( _Transitions[i]);
			}
		}

        public void AddMessages(XMLMessages _Messages)
        {
            for (int i = 0; i < _Messages.Count; i++)
            {
                vMessages.Add(_Messages[i]);
            }
        }

		public void AddActivities(XMLActivities _Activities)
		{
			for ( int i=0; i<_Activities.Count; i++)
			{
				vActivities.Add ( _Activities[i]);
			}
		}

		public void AddAttributes(WorkflowRelevantData.XMLAttributes _Attributes)
		{
			for ( int i=0; i<_Attributes.Count; i++)
			{
				vVariables.Add ( _Attributes[i]);
			}
		}

		public XMLActivity AddStartActivity()
		{
			XMLActivity activity = new XMLActivity();
			activity.SetToStart();

			vActivities.Add ( activity);

			return activity;
		}

		public XMLActivity AddEndActivity()
		{
			XMLActivity activity = new XMLActivity();
			activity.SetToEnd();

			vActivities.Add ( activity);

			return activity;
		}

		public XMLActivity AddActivity(string sActivityName)
		{
			XMLActivity activity = new XMLActivity();
			activity.Name = sActivityName;
			vActivities.Add ( activity);

			return activity;
		}

		public XMLActivity AddAutomaticActivity(string sActivityName)
		{
			XMLActivity activity = new XMLActivity();
			activity.Name = sActivityName;

			activity.Type = XMLActivity.API_TYPE;
			activity.Description = sActivityName;

			activity.XMLBehaviour.XMLBehaviourStart.OnlyOne = XMLBehaviourStart.YES_ONLYONE;
			activity.XMLBehaviour.XMLBehaviourStart.Mode = XMLBehaviourStart.AUTOMATIC_MODE;
			activity.XMLBehaviour.XMLBehaviourStart.Report = "Activity [Activity.Name] for the Process [WorkflowProcess.Name]";

			activity.XMLBehaviour.XMLBehaviourFinish.Mode = XMLBehaviourFinish.AUTOMATIC_MODE;

			activity.XMLBehaviour.XMLBehaviourExecution.Mode = XMLBehaviourExecution.AUTOMATIC_MODE;
			activity.XMLBehaviour.XMLBehaviourExecution.Report = "Activity [Activity.Name] for the Process [WorkflowProcess.Name]";
			activity.XMLBehaviour.XMLBehaviourExecution.Type = XMLBehaviourExecution.ROUTE_TYPE;
			activity.XMLBehaviour.XMLBehaviourExecution.XMLScript.Type = XMLScript.API_ASYNC_TYPE;
			activity.XMLBehaviour.XMLBehaviourExecution.XMLScript.Value = XMLScript.NONE_ACTION;

			vActivities.Add ( activity);

			return activity;
		}

		public XMLTransition AddTransition(XMLActivity activityBegin, XMLActivity activityEnd)
		{
            return this.AddTransition(activityBegin.Name, activityEnd.Name);
			
		}

        public XMLMessage AddMessage(XMLActivity activityBegin, XMLActivity activityEnd)
        {
            return this.AddMessage(activityBegin.Name, activityEnd.Name);
            
        }

		public XMLTransition AddTransition(string sActivityBegin, string sActivityEnd)
		{
			XMLTransition transition = new XMLTransition();
			transition.From = sActivityBegin;
			transition.To = sActivityEnd;
			transition.Set2Default();

			vTransitions.Add ( transition );

			return transition;
		}

        public XMLMessage AddMessage(string sActivityBegin, string sActivityEnd)
        {
            XMLMessage message = new XMLMessage();
            message.From = sActivityBegin;
            message.To = sActivityEnd;

            vMessages.Add(message);

            return message;
        }

		public void AddWorkflow(XMLWorkflow subWorkflow)
		{
			this.AddTransitions (subWorkflow.XMLTransitions );
            this.AddMessages(subWorkflow.XMLMessages);
			this.AddActivities (subWorkflow.XMLActivities );
			this.AddAttributes (subWorkflow.XMLAttributes);
		}

		public XMLActivity AddThrowerActivity(string sName)
		{
			XMLActivity activity = new XMLActivity();
			activity.Name = sName;

			activity.Type = XMLActivity.THROWER_TYPE;
			activity.Description = "";

			activity.XMLBehaviour.XMLBehaviourStart.OnlyOne = XMLBehaviourStart.YES_ONLYONE;
			activity.XMLBehaviour.XMLBehaviourStart.Mode = XMLBehaviourStart.AUTOMATIC_MODE;
			activity.XMLBehaviour.XMLBehaviourStart.Report = "Activity [Activity.Name] for the Process [WorkflowProcess.Name]";

			activity.XMLBehaviour.XMLBehaviourFinish.Mode = XMLBehaviourFinish.AUTOMATIC_MODE;

			activity.XMLBehaviour.XMLBehaviourExecution.Mode = XMLBehaviourExecution.AUTOMATIC_MODE;
			activity.XMLBehaviour.XMLBehaviourExecution.Report = "Activity [Activity.Name] for the Process [WorkflowProcess.Name]";
			activity.XMLBehaviour.XMLBehaviourExecution.Type = XMLBehaviourExecution.ROUTE_TYPE;
			activity.XMLBehaviour.XMLBehaviourExecution.XMLScript.Type = XMLScript.EVAL_EXPRESSION_TYPE;
			activity.XMLBehaviour.XMLBehaviourExecution.XMLScript.Value = XMLScript.NONE_ACTION;

			vActivities.Add ( activity);

			return activity;
		}

		
		public XMLActivity AddCatcherActivity(string sName, XMLActivity throwerActivity)
		{
			XMLActivity activity = this.AddAutomaticActivity(sName);
			activity.XMLBehaviour.XMLBehaviourStart.OnlyOne = XMLBehaviourStart.NO_ONLYONE;
			activity.Type = XMLActivity.CATCHER_TYPE;
			throwerActivity.ReferenceActivity = activity.Name;

			vActivities.Add ( activity);

			return activity;
		}

		public XMLActivity AddManaualActivity(string sName)
		{
			XMLActivity activity = new XMLActivity();
			activity.Name = sName;

			activity.Type = XMLActivity.API_TYPE;
			activity.Description = sName;

			activity.XMLBehaviour.XMLBehaviourStart.OnlyOne = XMLBehaviourStart.NO_ONLYONE;
			activity.XMLBehaviour.XMLBehaviourStart.Mode = XMLBehaviourStart.MANUAL_MODE;
			activity.XMLBehaviour.XMLBehaviourStart.Report = "Activity [Activity.Name] for the Process [WorkflowProcess.Name]";

			activity.XMLBehaviour.XMLBehaviourFinish.Mode = XMLBehaviourFinish.AUTOMATIC_MODE;

			activity.XMLBehaviour.XMLBehaviourExecution.Mode = XMLBehaviourExecution.MANUAL_MODE;
			activity.XMLBehaviour.XMLBehaviourExecution.Report = "Activity [Activity.Name] for the Process [WorkflowProcess.Name]";
			activity.XMLBehaviour.XMLBehaviourExecution.Type = XMLBehaviourExecution.ROUTE_TYPE;
			activity.XMLBehaviour.XMLBehaviourExecution.XMLScript.Type = XMLScript.API_ASYNC_TYPE;
			activity.XMLBehaviour.XMLBehaviourExecution.XMLScript.Value = XMLScript.NONE_ACTION;

			vActivities.Add ( activity);

			return activity;
		}

		public XMLActivity AddConditionActivity(string sName, string sCondition, bool bOnlyOne )
		{
			XMLActivity activity = new XMLActivity();
			activity.Name = sName;

			activity.Type = XMLActivity.CONDITION_TYPE;
			activity.Description = "";

			if ( bOnlyOne )
				activity.XMLBehaviour.XMLBehaviourStart.OnlyOne = XMLBehaviourStart.YES_ONLYONE;
			else
				activity.XMLBehaviour.XMLBehaviourStart.OnlyOne = XMLBehaviourStart.NO_ONLYONE;

			activity.XMLBehaviour.XMLBehaviourStart.Mode = XMLBehaviourStart.AUTOMATIC_MODE;
			activity.XMLBehaviour.XMLBehaviourStart.Report = "Activity [Activity.Name] for the Process [WorkflowProcess.Name]";

			activity.XMLBehaviour.XMLBehaviourFinish.Mode = XMLBehaviourFinish.AUTOMATIC_MODE;

			activity.XMLBehaviour.XMLBehaviourExecution.Mode = XMLBehaviourExecution.AUTOMATIC_MODE;
			activity.XMLBehaviour.XMLBehaviourExecution.Report = "Activity [Activity.Name] for the Process [WorkflowProcess.Name]";
			activity.XMLBehaviour.XMLBehaviourExecution.Type = XMLBehaviourExecution.ROUTE_TYPE;
			activity.XMLBehaviour.XMLBehaviourExecution.XMLScript.Type = XMLScript.EVAL_EXPRESSION_TYPE;
			activity.XMLBehaviour.XMLBehaviourExecution.XMLScript.Value = sCondition;

			vActivities.Add ( activity);

			return activity;
		}

		public XMLActivity AddApplicationActivity(string sName, WorkflowApplicationsData.XMLApplicationFunction function)
		{
			XMLActivity activity = new XMLActivity();
			activity.Name = sName;

			activity.Type = XMLActivity.APPLICATION_TYPE;
			activity.Description = "";

			activity.XMLBehaviour.XMLBehaviourStart.OnlyOne = XMLBehaviourStart.YES_ONLYONE;
			activity.XMLBehaviour.XMLBehaviourStart.Mode = XMLBehaviourStart.AUTOMATIC_MODE;
			activity.XMLBehaviour.XMLBehaviourStart.Report = "Activity [Activity.Name] for the Process [WorkflowProcess.Name]";

			activity.XMLBehaviour.XMLBehaviourFinish.Mode = XMLBehaviourFinish.AUTOMATIC_MODE;

			activity.XMLBehaviour.XMLBehaviourExecution.Mode = XMLBehaviourExecution.AUTOMATIC_MODE;
			activity.XMLBehaviour.XMLBehaviourExecution.Report = "Activity [Activity.Name] for the Process [WorkflowProcess.Name]";
			activity.XMLBehaviour.XMLBehaviourExecution.Type = XMLBehaviourExecution.ROUTE_TYPE;
			activity.XMLBehaviour.XMLBehaviourExecution.XMLScript.Type = XMLScript.APPLICATION_API_TYPE;
			activity.XMLBehaviour.XMLBehaviourExecution.XMLScript.Value = function.GetXML();

			vActivities.Add ( activity);

			return activity;
		}

		/** STATIC METHODS **/

		/** no static methods **/
	}
}